package com.sx.pipeline.ui.map

import android.graphics.Color
import android.os.Bundle
import com.alibaba.android.arouter.facade.annotation.Autowired
import com.alibaba.android.arouter.facade.annotation.Route
import com.amap.api.maps.AMap
import com.amap.api.maps.CameraUpdate
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.CoordinateConverter
import com.amap.api.maps.model.*
import com.amap.api.services.core.AMapException
import com.amap.api.services.district.DistrictItem
import com.amap.api.services.district.DistrictSearch
import com.amap.api.services.district.DistrictSearchQuery
import com.blankj.utilcode.util.CollectionUtils
import com.blankj.utilcode.util.ThreadUtils
import com.blankj.utilcode.util.ToastUtils
import com.sx.mvvmlibs.base.BaseViewModel
import com.sx.mvvmlibs.event.SingleLiveEvent
import com.sx.mvvmlibs.http.CommonObserver
import com.sx.mvvmlibs.utils.Logs
import com.sx.mvvmlibs.utils.RxThreadHelper
import com.sx.pipeline.R
import com.sx.pipeline.app.base.CYBaseAppBarActivity
import com.sx.pipeline.app.config.IntentKey
import com.sx.pipeline.app.model.CYBaseViewModel
import com.sx.pipeline.arouth.RoutePath
import com.sx.pipeline.databinding.ActShowLocationBinding
import com.sx.pipeline.repos.http.req.DistrictBorderDTO
import com.sx.pipeline.repos.http.res.Ipage
import com.sx.pipeline.repos.http.res.TerritoryVO
import com.sx.pipeline.repos.local.db.table.PipeFileBeanDO
import com.sx.pipeline.ui.map.entity.DrawLatLng
import com.sx.pipeline.ui.map.tools.DrawMapUtils
import io.reactivex.rxjava3.android.schedulers.AndroidSchedulers
import io.reactivex.rxjava3.core.Single
import io.reactivex.rxjava3.functions.Consumer
import io.reactivex.rxjava3.schedulers.Schedulers

/**
 * @Author: YY
 * @Date: 2022/7/8
 * @Desc: 显示地点
 */
@Route(path = RoutePath.Main.SHOW_LOCATION)
class ShowLocationActivity: CYBaseAppBarActivity<ActShowLocationBinding, CYBaseViewModel>
    (R.layout.act_show_location) {
    @JvmField
    @Autowired(name = "lat")
    var lat: String?=""
    @JvmField
    @Autowired(name = "lon")
    var lon: String?=""
    @JvmField
    @Autowired(name = "address")
    var address: String?=""
    private lateinit var aMap: AMap
    private var marker: Marker? = null
    private var point: LatLng? = null

    override fun initAppBar() {
        getTitleBar().title = "施工地点"
    }

    override fun onSaveInstanceState(outState: Bundle) {
        super.onSaveInstanceState(outState)
        mBinding.mapView.onSaveInstanceState(outState)
    }

    override fun initData(bundle: Bundle?) {
        super.initData()
        mBinding.mapView.onCreate(bundle)
        mBinding.tvAddress.text=address
        if (!this::aMap.isInitialized) {
            aMap = mBinding.mapView.map
        }
        if (marker == null) {
            point = lat?.toDouble()?.let { lon?.toDouble()?.let { it1 -> LatLng(it, it1) } }
            //地图发生变化之后描绘mark
            marker = aMap.addMarker(
                MarkerOptions()
                .position(point)
                .icon(BitmapDescriptorFactory.fromResource(R.drawable.icon_select_point)))
            // 移动marker
            aMap.moveCamera(CameraUpdateFactory.newCameraPosition(CameraPosition(point, 11.2f, 0f, 0f)))
        }

        ThreadUtils.getMainHandler()
            .postDelayed({
                //我的管线
                getLocalMapList()
            },200)
        ThreadUtils.getMainHandler()
            .postDelayed({
                //负责区域
                getTerritoryList()
            },500)
        ThreadUtils.getMainHandler()
            .postDelayed({
                //行政
                getDistrictBorderList()
            },700)

    }

    fun getLocalMapList() {
        mViewModel.addSubscribe(
            Single.merge(mViewModel.mModel.getFileBeanAll(0), mViewModel.mModel.getFileBeanAll(1))
                .collectInto(ArrayList<PipeFileBeanDO>(),{ list, valueList->valueList.forEach { list.add(it) }})
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(Consumer {
                    if(!CollectionUtils.isEmpty(it)){
                        getMapObj(it)
                    }
                })
        )
    }

    /**
     * 根据类型 转换 坐标
     */
    fun convert(sourceLatLng: LatLng?): LatLng? {
        val converter = CoordinateConverter(this)
        // CoordType.GPS 待转换坐标类型
        converter.from(CoordinateConverter.CoordType.GPS)
        // sourceLatLng待转换坐标点
        converter.coord(sourceLatLng)
        // 执行转换操作
        return converter.convert()
    }

    fun getMapObj(PipeFileBeanDOBeanList: List<PipeFileBeanDO>) {
        PipeFileBeanDOBeanList.forEachIndexed { index, pipeFileBeanDO ->
            // 绘制点列表
            val pointList2: MutableList<DrawLatLng> = mutableListOf()
            pipeFileBeanDO.fileNodesBeanDO?.forEach {
                val latLng = LatLng(it.latitude, it.longitude.toDouble())
                var drawLatLng = DrawLatLng(convert(latLng)!!, false)
                pointList2.add(drawLatLng)
                if (pointList2.size > 0) {
                    this.aMap.addPolyline(PolylineOptions().addAll(DrawMapUtils.drawLatLngToLatLng(
                            pointList2)).width(2f).color(Color.parseColor("#FF0000"))
                            .zIndex(999f))  // 线颜色
                    
                }
            }
        }

    }

    // 绘制点列表
    private val pointList: MutableList<DrawLatLng> = mutableListOf()
    fun getTerritoryList(){
        mViewModel.addSubscribe(mViewModel.mModel.getTerritoryList(-1, isPage = false, page = 0)
            .compose(RxThreadHelper.rxSchedulerHelper())
            .subscribeWith(object : CommonObserver<Ipage<TerritoryVO>, BaseViewModel<*>>
                (mViewModel, true) {
                override fun onResult(result: Ipage<TerritoryVO>) {
                    if (result != null && result.records.isNotEmpty()) {
                        showTerritory(result.records)
                    }
                }

                override fun onFailed(code: Int, msg: String?) {
                    super.onFailed(code, msg)

                }
            })
        )
    }

    /**
     * 显示负责区域
     */
    private fun showTerritory(territoryList: List<TerritoryVO>) {
        var drawLatLng: DrawLatLng
        if (territoryList.isNotEmpty()) {
            territoryList.forEach { territoryVO ->
                pointList.clear()
                territoryVO.centerList.forEach { centerList ->
                    val latLng =
                        LatLng(centerList.latitude.toDouble(), centerList.longitude.toDouble())
                    drawLatLng = DrawLatLng(latLng, false)
                    if (territoryVO?.type != 0) {
                        drawLatLng = DrawLatLng(convert(latLng)!!, false)
                    }
                    pointList.add(drawLatLng)
                }
                drawPolygon()
            }
        }
    }


    /**
     * 绘制多边形
     */
    private fun drawPolygon() {
        if (pointList.size <= 2) {
            return
        }
        // 多边形参数对象
        val polygonOptions = PolygonOptions()
        // 添加 多边形的每个顶点（顺序添加）
        for (i in pointList.indices) {
            polygonOptions.add(pointList[i].latLng)
            Logs.d("drawPolygon ${pointList[i].latLng}")
        }
        polygonOptions.strokeWidth(2f)
            .strokeColor(Color.parseColor("#ffffff")) // 边框颜色
            .fillColor(Color.parseColor("#66000000")) // 多边形的填充色
        Logs.d("drawPolygon ")
        val polygon = this.aMap.addPolygon(polygonOptions)
        Logs.d("drawPolygon ")
    }

    fun getDistrictBorderList() {
        mViewModel.addSubscribe(mViewModel.mModel.getDistrictBorderList(1, limit = 9999)
            .compose(RxThreadHelper.rxSchedulerHelper())
            .subscribeWith(object : CommonObserver<Ipage<DistrictBorderDTO>, BaseViewModel<*>>
                (mViewModel, true) {

                override fun onResult(result: Ipage<DistrictBorderDTO>) {
                    Logs.d("getTerritoryList ${result.records.size}")
                    if(!CollectionUtils.isEmpty(result.records)){
                        result.records.forEach {
                            searchDistrict(it.name)
                        }
                    }

                }

                override fun onFailed(code: Int, msg: String?) {
                    super.onFailed(code, msg)
                }
            })
        )
    }

    // 行政区域
    private var districtPoints: MutableList<Polyline> = mutableListOf()

    /**
     * 搜索行政区
     */
    private fun searchDistrict(searchName: String, provincesName: String? = null, address: String? = null) {
        val search = DistrictSearch(this)
        val query = DistrictSearchQuery(provincesName, DistrictSearchQuery.KEYWORDS_CITY, 0)
        // 是否返回边界值
        query.isShowBoundary = true
        //不显示子区域边界
        query.isShowChild = false
        query.keywords = searchName
        search.query = query
        search.setOnDistrictSearchListener { districtResult ->
            if (districtResult?.district != null) {
                if (districtResult.aMapException.errorCode == AMapException.CODE_AMAP_SUCCESS) {
                    Logs.d("polygonDraw: " + districtResult.pageCount)
                    Logs.d("polygonDraw: " + districtResult.district.size)
                    polygonDraw(districtResult.district, address)
                }
            }
        }
        // 开始搜索
        search.searchDistrictAsyn()
    }

    private fun polygonDraw( data: List<DistrictItem>, address: String? = null) {
        ThreadUtils.executeBySingle(object : ThreadUtils.Task<ArrayList<LatLng>?>() {
            override fun doInBackground(): ArrayList<LatLng>? {
                val points: ArrayList<LatLng> = ArrayList()
                if (data.isNotEmpty()) {
                    val boundary = data[0].districtBoundary()
                    Logs.d("polygonDraw ${boundary.size}")
                    if (boundary.isNotEmpty()) {
                        val center = data[0].center
                        var index = 0
                        var count = 0
                        for (i in boundary.indices) {
                            if (boundary[i].length >= count) {
                                count = boundary[i].length
                                index = i
                            }
                        }
                        val str = boundary[index]
                        val latLngList = str.split(";".toRegex()).toTypedArray()
                        for (element in latLngList) {
                            val latLngStr: List<String> = element.split(",")
                            if (latLngStr.size == 2) {
                                try {
                                    val lng = latLngStr[0].toDouble()
                                    val lat = latLngStr[1].toDouble()
                                    points.add(LatLng(lat, lng))
                                } catch (e: Exception) {
                                    Logs.e("onDistrictSearched: cast error")
                                }
                            }
                        }
                    }
                    return points
                }
                return null
            }

            override fun onSuccess(result: ArrayList<LatLng>?) {
//                districtPoints = result
                //显示行政区域范围

                val addPolyline = aMap.addPolyline(PolylineOptions().addAll(result).width(10f).color(Color.BLUE).setDottedLine(false))
                districtPoints.add(addPolyline)
            }

            override fun onCancel() {

            }

            override fun onFail(t: Throwable?) {

            }

        })
    }

    override fun onResume() {
        super.onResume()
        mBinding.mapView.onResume()
    }

    override fun onPause() {
        super.onPause()
        mBinding.mapView.onPause()
    }

    override fun onDestroy() {
        mBinding.mapView.onDestroy()
        super.onDestroy()
    }
}